package com.zimmur.service.impl.account;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.zimmur.common.ReturnJsonEntity;
import com.zimmur.common.StatusCodeEnum;
import com.zimmur.dao.IUserDao;
import com.zimmur.dao.account.ICouponChannelDao;
import com.zimmur.dao.account.ICouponDetailDao;
import com.zimmur.dao.account.ICouponStockDao;
import com.zimmur.dao.account.IStockChannelDao;
import com.zimmur.model.account.CouponChannel;
import com.zimmur.model.account.CouponDetail;
import com.zimmur.model.account.CouponStock;
import com.zimmur.model.account.StockChannel;
import com.zimmur.model.account.User;
import com.zimmur.model.account.view.CouponView;
import com.zimmur.service.account.ICouponService;
import com.zimmur.tools.CouponCodeUtils;
import com.zimmur.tools.DateUtils;
@Service("couponService")
public class CouponServiceImpl implements ICouponService{
	private Logger log = LoggerFactory.getLogger(CouponServiceImpl.class);
	@Resource
	private ICouponDetailDao couponDetailDao;
	@Resource
	private IUserDao userDao;
	@Resource
	private ICouponChannelDao couponChannelDao;
	@Resource
	private ICouponStockDao couponStockDao;
	@Resource
	private IStockChannelDao stockChannelDao;
	
	private static Object couponStockLock=new Object();
	private static Object couponLock=new Object();
	private static Object stockChannelLock=new Object();
	
	@Override
	public List<CouponView> selectByUserId(long userId, int mininum,int isUsePercent,int isPrepay) {
		int time=DateUtils.getNowUnixTime();
		User user=userDao.selectUserInfoByUserId(userId);
		List<CouponView> couponViewList=new ArrayList<>();
		if(user!=null && user.getMobileNo()!=null && !user.getMobileNo().isEmpty()){
			if(isPrepay == 0){
				isPrepay = 1;
			}
			if(isPrepay == 1){
				isPrepay = 2;
			}
			 List<CouponDetail> couponDetails=couponDetailDao.selectCouponByMobileNo(user.getMobileNo(), time,mininum
					 ,isUsePercent,isPrepay);
			 Iterator<CouponDetail> iterator= couponDetails.iterator();
			while (iterator.hasNext()) {
				CouponDetail couponDetail = iterator.next();
				if (couponDetail != null) {
					CouponView couponView = decorateCoupon(couponDetail, mininum);
					couponViewList.add(couponView);
				}
			}
		}
		return couponViewList;
	}
	@Override
	public List<CouponView> selectAllCouponByMobileNo(long userId) {
		User user=userDao.selectUserInfoByUserId(userId);
		List<CouponView> couponViewList=new ArrayList<>();
		if(user!=null && user.getMobileNo()!=null && !user.getMobileNo().isEmpty()){
			 List<CouponDetail> couponDetails=couponDetailDao.selectAllCouponByMobileNo(user.getMobileNo());
			 Iterator<CouponDetail> iterator= couponDetails.iterator();
			while (iterator.hasNext()) {
				CouponDetail couponDetail = iterator.next();
				if (couponDetail != null) {
					CouponView couponView = decorateCoupon(couponDetail,0);
					couponViewList.add(couponView);
				}
			}
		}
		return couponViewList;
	}
	/**
	 * 优惠券转View
	* @Title: decorateCoupon 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param couponDetail
	* @param couponView  
	* @return void    返回类型
	 */
	private CouponView decorateCoupon(CouponDetail couponDetail,int orderJe) {
		CouponView couponView = new CouponView();
		couponView.setCouponId(couponDetail.getCouponId());
		 couponView.setType(couponDetail.getCouponStockType());
		 couponView.setCouponDiscount(couponDetail.getCouponDiscount());
		 String couponName="";
		 int minimum=couponDetail.getCouponMininum()/100;
		 if("cash".equals(couponDetail.getCouponStockType())){
			 int cash=couponDetail.getCouponValue()/100;
			 if(minimum==0){
				 couponName=cash+"元抵扣券(无限额)";
			 }else{
				 
				 couponName="满"+minimum+"元减"+cash+"元";
			 }
		 }else{
			 int discount=couponDetail.getCouponDiscount();
			 if(minimum==0){
				 if(discount%10==0){
					 couponName=discount/10+"折折扣券(无限额)";
				 }else{
					 couponName=discount/10.0+"折折扣券(无限额)";
				 }
			 }else{
				 if(discount%10==0){
					 couponName="满"+minimum+"元打"+discount/10+"折";
				 }else{
					 couponName="满"+minimum+"元打"+discount/10.0+"折";
				 }
			 }
		 }
		 couponView.setCouponName(couponName);
		 couponView.setCouponNameText(couponDetail.getCouponName());
		 couponView.setCouponValue(couponDetail.getCouponValue());
		 //有效期
		 String timeArea=DateUtils.getFormatDateFromUnixTime(couponDetail.getBeginTime())+"-"+DateUtils.getFormatDateFromUnixTime(couponDetail.getEndTime());
		 couponView.setTimeArea(timeArea);
		 if(orderJe>0){
			 double je=0;
			 if("cash".equals(couponDetail.getCouponStockType())){
				 je=(orderJe-couponDetail.getCouponValue())/100.00;
			 }else if("discount".equals(couponDetail.getCouponStockType())){
				 je=orderJe*couponDetail.getCouponDiscount()/10000.00;
			 }
			 BigDecimal couponJe=new BigDecimal(je);
			 couponJe=couponJe.setScale(2, BigDecimal.ROUND_DOWN);
			 couponView.setCouponJe(couponJe);
		 }
		 couponView.setCouponState(couponDetail.getCouponState());//优惠券状态
		 return couponView;
	}
	@Override
	public CouponDetail selectCouponByCouponId(int couponId) {
		
		return couponDetailDao.selectCouponByCouponId(couponId);
	}

	@Override
	public int updateCoupon(CouponDetail couponDetail) {
		return couponDetailDao.updateByPrimaryKeySelective(couponDetail);
	}

	@Override
	public int addOneCoupon(CouponDetail couponDetail) {
		
		return couponDetailDao.addCouponDetail(couponDetail);
	}

	@Override
	public int addCouponList(List<CouponDetail> couponDetailList) {
		return couponDetailDao.addCouponDetailList(couponDetailList);
	}

	@Override
	public List<CouponStock> selectStockByChannelId(Integer channelId,String mobileNo) {
		
		return couponStockDao.selecStocktByChannelId(channelId,mobileNo);
	}

	@Override
	public List<CouponChannel> selectChannelByType(String type) {
		
		return couponChannelDao.selectByType(type);
	}

	@Override
	public int updateCouponStock(Integer stockId,int used,int send,int locked) {
		int flag=0;
		synchronized (couponStockLock) {
			try {
				CouponStock couponStock=couponStockDao.selectByStockId(stockId);
				if(used==1){
					couponStock.setUsedNum(couponStock.getUsedNum()+used);
				}else{
					couponStock.setUsedNum(null);
				}
				if (send>0) {
					couponStock.setIsSendNum(couponStock.getIsSendNum()+send);
				} else {
					couponStock.setIsSendNum(null);
				}
				if (locked==0) {
					couponStock.setLockedNum(null);
				} else {
					couponStock.setLockedNum(couponStock.getLockedNum()+locked);
				}
				flag=couponStockDao.updateStock(couponStock);
			} catch (Exception e) {
				log.error("update coupon_stock error:"+e.getMessage());
			}
		}
		return flag;
	}

	@Override
	public int createCouponByMobileNo(String mobileNo,String type) {
		int flag=0;
		List<CouponChannel> couponChannels=couponChannelDao.selectByType(type);
		if (couponChannels!=null && couponChannels.size()>0) {
			synchronized (couponLock) {
				
				try {
					List<CouponDetail> couponDetailList=new ArrayList<>();
					
					for(CouponChannel couponChannel:couponChannels){
						int channelId=couponChannel.getChannelId();
						List<CouponStock> couponStocks = selectStockByChannelId(channelId, mobileNo);
						Iterator<CouponStock> iterator=couponStocks.iterator();
						int maxQuota=0;
						int total=0;
						int send=0;
						int createSend=0;
						while(iterator.hasNext()){
							CouponStock couponStock=iterator.next();
							createSend=0;
							maxQuota=couponStock.getMaxQuota();
							total=couponStock.getCouponTotal();
							send=couponStock.getIsSendNum();
							for(int i=0;i<maxQuota;i++){
								if(total>send){
									CouponDetail couponDetail =	createCouponByStock(mobileNo,couponStock,channelId,send,type);
									if(couponDetail!=null){
										couponDetailList.add(couponDetail);
										send++;
										createSend++;
									}
								}else{
									break;
								}
							}
							if(createSend>0){
								updateCouponStock(couponStock.getCouponStockId(), 0, createSend, 0);
								updateStockChannel(couponStock.getCouponStockId(), channelId, createSend);
							}
						}
					}
					
					if(!couponDetailList.isEmpty()){
						flag=addCouponList(couponDetailList);
					}
				} catch (Exception e) {
					log.error(e.getMessage(),e);
				}
			}
		}
		return flag;
	}
	
	private CouponDetail createCouponByStock(String mobileNo,CouponStock couponStock,int channelId,int send,String source){
		CouponDetail couponDetail=new CouponDetail();
		String couponCode=CouponCodeUtils.getCode(couponStock.getCouponTotal(), send);
		if("#00".equals(couponCode)){
			return null;
		}
		couponDetail.setCouponCode(couponCode);
		couponDetail.setCouponStockId(couponStock.getCouponStockId());
		couponDetail.setMobileNo(mobileNo);
		couponDetail.setCouponStockType(couponStock.getCouponStockType());
		couponDetail.setCouponDiscount(couponStock.getCouponDiscount());
		couponDetail.setCouponValue(couponStock.getCouponValue());
		couponDetail.setCouponMininum(couponStock.getCouponMininum());
		couponDetail.setCouponName(couponStock.getCouponName());
		couponDetail.setCouponState("2");
		couponDetail.setCouponDesc(couponStock.getCouponDesc());
		couponDetail.setUseByPercent(couponStock.getUseByPercent());
		couponDetail.setUseByGoods(couponStock.getUseByGoods());
		
		//根据领取时间计算
		if(couponStock.getTimeType().equals("day")){
			int beginTime=DateUtils.getNowUnixTime();
			int endTime=beginTime+couponStock.getEffectiveDay()*24*60*60;
			couponDetail.setBeginTime(beginTime);
			couponDetail.setEndTime(endTime);
		}else{
			//根据批次时间计算
			couponDetail.setBeginTime(couponStock.getBeginTime());
			couponDetail.setEndTime(couponStock.getEndTime());
			
		}
		couponDetail.setSendTime(DateUtils.getNowUnixTime());
		couponDetail.setSendSource(source);
		couponDetail.setChannelId(channelId);
		couponDetail.setCouponDesc(couponStock.getCouponDesc());
		return couponDetail;
	}

	@Override
	public List<CouponDetail> selectCouponByOrderId(Long orderId) {
		List<CouponDetail> details=null;
		try {
			details = couponDetailDao.selectCouponByOrderId(orderId);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
		}
		return details;
	}
	
	private int  updateStockChannel(Integer couponStockId,Integer channelId , int num){
		int flag=0;
		synchronized (stockChannelLock) {
			try {
				StockChannel stockChannel=stockChannelDao.selectByPrimaryKey(channelId,couponStockId);
				if(stockChannel!=null){
					int send=stockChannel.getSendNum()==null ?0:stockChannel.getSendNum();
					stockChannel.setSendNum(num+send);
					flag=stockChannelDao.updateByPrimaryKey(stockChannel);
				}
			} catch (Exception e) {
				log.error(e.getMessage(),e);
			}
		}
		return flag;
	}
	@Override
	public ReturnJsonEntity queryValidCoupon(String couponCode, String mobileNo,int orderJe,int isUsePercent,int isPrepay) {
		ReturnJsonEntity entity = new ReturnJsonEntity();
		StatusCodeEnum status=StatusCodeEnum.CODE100000;
		Integer currentTime =DateUtils.getUnixTimeByDate(DateUtils.getNow());
		CouponDetail couponDetail = couponDetailDao.selectValidCoupon(couponCode, mobileNo);
		if (couponDetail != null) {
			if (couponDetail.getBeginTime() > currentTime) {
				status = StatusCodeEnum.CODE700304;
			} else if (couponDetail.getEndTime() < currentTime) {
				status = StatusCodeEnum.CODE700302;
			} else if (couponDetail.getCouponMininum() >= orderJe) {
				status = StatusCodeEnum.CODE700303;
			} else if (!validateCoupon(couponDetail, isUsePercent, isPrepay)) {
				status = StatusCodeEnum.CODE700305;
			} else {
				entity.setData(decorateCoupon(couponDetail, orderJe));
				status = StatusCodeEnum.CODE000000;
			}
		} else {
			status = StatusCodeEnum.CODE700302;
		}
		entity.setCode(status.getCode());
		entity.setMsg(status.getMsg());
		return entity;
	}
	/**
	 * 检查优惠券是否适用
	* @Title: validateCoupon 
	* @Description: 检查优惠券是否适用当前订单 
	* @param coupon
	* @param useByPercent 是否含折扣商品 0=不包含 1=包含
	* @param isPrepay 是否含预售 0=不包含 1=包含
	* @return boolean    返回类型
	 */
	private boolean validateCoupon(CouponDetail coupon,int useByPercent,int isPrepay){
		if(coupon == null){
			return false;
		}
		if(useByPercent == 1 && (coupon.getUseByPercent()==0)){
			return true;
		}
		if(isPrepay == 1 && (coupon.getUseByGoods()==2 || coupon.getUseByGoods()==0)){
			return true;
		}
		if(coupon.getUseByPercent()==useByPercent && coupon.getUseByGoods()==isPrepay){
			return true;
		}
		return false;
	}
}
